/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ai.gui;

import ai.*;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Observable;
import java.util.Observer;
import java.util.Vector;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.Timer;
import uk.ac.bath.gui.*;
import uk.ac.bath.util.Tweakable;

/**
 * The application's main frame.
 */
public class AIPanel extends JPanel implements Observer {

    //   private TrainingFileReader trainingLabelReader;
    //  private Brain brain;
    //  Random rand = new Random();
    //  TrainingFileReader trainingReader;
    private ImagePanel imaginationPanel[];
    private javax.swing.JButton nextTraining;
    private javax.swing.JButton nextTest;
    private javax.swing.JButton allTraining;
    private javax.swing.JProgressBar progressBar;
    private ImageLabelPanel realityPanel;

    private javax.swing.JLabel statusMessageLabel;
    private javax.swing.JPanel statusPanel;
 
    private AIModel model;
    private JButton allTest;
    private DigitResultPanel digitResultPanel;
    private Timer timer;
    private Progressable progressable;
    private JButton contTraining;
    private JButton stopBut;
    private boolean stop;
    private ImageLabelPanel fantasyPanel;
    private ImageLabel reality;
    private ImageLabel fantasy;
    private JButton oneTraining;

    public AIPanel(AIModel model) {
        this.model = model;
        initComponents();
    }

    @SuppressWarnings("unchecked")
    private void initComponents() {
        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));



        add(createButtons());
        add(createImagePanel());


        JPanel p = new JPanel();

        p.setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.gridx = 0;
        Vector<Tweakable> tweaks = model.getBrain().getTweaks();

        if (tweaks != null) {
            System.out.println(" Added tweaks ");
            TweakerPanel tp = new TweakerPanel(1, tweaks.size());
            tp.setPreferredSize(new Dimension(200, 100));
            for (Tweakable t : tweaks) {
                TextTweaker tt = new TextTweaker(t);
                tp.addComponent(tt.getComponent());
                tp.newRow();
            }
            c.weightx = 1.0;
            p.add(tp, c);
            c.gridx++;

        }
        realityPanel = new ai.gui.ImageLabelPanel(3);
        realityPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Reality"));

        p.add(realityPanel, c);
        c.gridx++;

        fantasyPanel = new ai.gui.ImageLabelPanel(3);
        fantasyPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Fantasy"));

        p.add(fantasyPanel, c);
        c.gridx++;

        digitResultPanel = new DigitResultPanel();

        p.add(digitResultPanel, c);
        c.gridx++;

        add(p);

        statusPanel = new javax.swing.JPanel();

        javax.swing.JSeparator statusPanelSeparator = new javax.swing.JSeparator();
        statusMessageLabel = new javax.swing.JLabel();


        add(statusPanel);
        statusPanel.add(statusMessageLabel);
        statusPanel.add(statusPanelSeparator);
        statusPanel.setBorder(javax.swing.BorderFactory.createLoweredBevelBorder());
        statusMessageLabel.setText("Why not hit a button");
        progressBar = new JProgressBar();
        statusPanel.add(progressBar);
        timer = new Timer(500, new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                int progress = 0;
                if (progressable != null) {
                    progress = (int) (100 * progressable.getProgress());
                }
                progressBar.setValue(progress);
                update(null, null);
            }
        });

        validate();
        timer.start();
        timer.setRepeats(true);
    }

    static int count=0;
    
    JPanel createButtons() {

        JPanel buts = new JPanel();

        oneTraining = new javax.swing.JButton();
        buts.add(oneTraining);

        nextTraining = new javax.swing.JButton();
        buts.add(nextTraining);

        allTraining = new javax.swing.JButton();
        buts.add(allTraining);

        contTraining = new javax.swing.JButton();
        buts.add(contTraining);

        nextTest = new javax.swing.JButton();
        buts.add(nextTest);

        allTest = new javax.swing.JButton();
        buts.add(allTest);


        stopBut = new javax.swing.JButton();
        buts.add(stopBut);

        nextTraining.setText("NEXT MISS");


        nextTraining.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent evt) {
                model.nextMiss();
    //                          model.dump();
            }
        });


        nextTest.setText("TEST NEXT");

        nextTest.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent evt) {
                model.nextTest();
  //                            model.dump();
            }
        });



        oneTraining.setText("TRAIN ONE");

        oneTraining.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(ActionEvent evt) {

                model.nextTrain();
  //              model.dump();
            }
        });


        allTraining.setText("TRAIN ALL");

        allTraining.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(ActionEvent evt) {

                progressable = model;
                Thread t = new Thread() {

                    @Override
                    public void run() {
                        setWorking(true);
                        model.allTraining();
                        model.allTest();
                        progressable = null;
                        setWorking(false);
                    }
                };

                t.start();

            }
        });



        contTraining.setText("TRAIN FOREVER");

        contTraining.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(ActionEvent evt) {

                progressable = model;
                Thread t = new Thread() {

                    @Override
                    public void run() {

                        stop = false;
                        while (!stop) {
                            setWorking(true);
                            model.allTraining();
                            model.allTest();
                        }
                        progressable = null;
                        setWorking(false);
                    }
                };

                t.start();

            }
        });


        allTest.setText("TEST ALL");

        allTest.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(
                    java.awt.event.ActionEvent evt) {

                progressable = model;

                Thread t = new Thread() {

                    @Override
                    public void run() {
                        setWorking(true);
                        model.allTest();
                        setWorking(false);
                        progressable = null;
                    }
                };

                t.start();
            }
        });




        stopBut.setText("STOP");

        stopBut.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(
                    java.awt.event.ActionEvent evt) {
                stop = true;
                model.stop();
            //   stopBut.setEnabled(false);
            }
        });

        stopBut.setEnabled(false);

        return buts;

    }

    void setWorking(boolean yes) {
        oneTraining.setEnabled(!yes);
        allTraining.setEnabled(!yes);
        nextTraining.setEnabled(!yes);
        contTraining.setEnabled(!yes);
        allTest.setEnabled(!yes);
        nextTest.setEnabled(!yes);
        stopBut.setEnabled(yes);
    }

    JComponent createImagePanel() {

        JScrollPane scroll = new JScrollPane();

        JPanel main = new JPanel();
        scroll.setViewportView(main);

        GridBagLayout bag = new GridBagLayout();
        main.setLayout(bag);
        GridBagConstraints c = new GridBagConstraints();
        c.gridx = 0;
        c.gridy = 0;
        int n = model.getBrain().getImaginationCount();

        imaginationPanel = new ImagePanel[n];
//
//        float area=800*400;
//        float areaI=area/n;
//        float size=(float) Math.sqrt(areaI);
//        
//        int scale=Math.max(1,Math.min((int)(size/30),3));


        int nPerRow = 10;
        LayoutHint dl = model.getLayoutHint();
        if (dl != null) {
             nPerRow = dl.nPerRow;
        }
        int scale = Math.max(1, Math.min(3, 1500 / 30 / nPerRow));



        for (int i = 0; i < n; i++) {
            imaginationPanel[i] = new ImagePanel(scale);

            bag.setConstraints(imaginationPanel[i], c);
            c.gridx++;
            if (c.gridx >= nPerRow) {
                c.gridx = 0;
                c.gridy++;
            }
            main.add(imaginationPanel[i]);

            imaginationPanel[i].setBorder(javax.swing.BorderFactory.createLoweredBevelBorder());
            imaginationPanel[i].setName("imaginationPanel"); // NOI18N
            Image imag = model.getBrain().getImagination(i);
            imaginationPanel[i].setImage(imag);
        }

        return scroll;

    }

    public void update(Observable o, Object arg) {

        //     System.out.println("UPDATE");


        Result result = model.getLatestResult();
        if (result == null) {
            return;
        }
        if (reality == null) {
            reality = new ImageLabel(new FloatVectorImage(result.in.image, model.getImageDimension(), "Reality"), -1);
        }
        if (fantasy == null) {
            fantasy = new ImageLabel(new FloatVectorImage(result.out.image, model.getImageDimension(), "Fantasy"), -1);
        }

        reality.setData(result.in.image, result.in.label);

        fantasy.setData(result.out.image, result.out.label);

        realityPanel.setImageLabel(reality);
        fantasyPanel.setImageLabel(fantasy);

        // for (int i = 0; i < 10; i++) {
        //     imaginationPanel[i].repaint();
        // }

        statusMessageLabel.setText(model.getStatusString());
        digitResultPanel.set(result.out.label, result.in.label);
        repaint();
    }
}

